package com.md2ppt.engine;

import com.md2ppt.config.PresentationConfig;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.PictureData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Path;

/**
 * Apache POI引擎实现
 * 作为Aspose.Slides的开源替代方案
 */
public class PoiEngine implements PresentationEngine {
    
    private static final Logger logger = LoggerFactory.getLogger(PoiEngine.class);
    
    @Override
    public String getEngineName() {
        return "Apache POI XSLF";
    }
    
    @Override
    public boolean isAvailable() {
        try {
            Class.forName("org.apache.poi.xslf.usermodel.XMLSlideShow");
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
    
    @Override
    public EngineCapabilities getCapabilities() {
        return new EngineCapabilities(
            false,  // 有限的动画支持
            false,  // 不支持高级效果
            false,  // 不支持视频嵌入
            true,   // 支持基本主题
            0       // 无动画效果
        );
    }
    
    @Override
    public GenerationResult generatePresentation(PresentationConfig config, Path outputPath) {
        long startTime = System.currentTimeMillis();
        
        try {
            logger.info("使用Apache POI生成演示文稿: {}", outputPath);
            
            XMLSlideShow presentation = new XMLSlideShow();
            
            // 配置演示文稿属性
            configurePresentationProperties(presentation, config);
            
            // 生成幻灯片
            GenerationStatistics stats = generateSlides(presentation, config);
            
            // 保存文件
            savePresentation(presentation, outputPath);
            
            long processingTime = System.currentTimeMillis() - startTime;
            
            logger.info("POI演示文稿生成完成，耗时: {}ms", processingTime);
            
            return new GenerationResult(
                true,
                "演示文稿生成成功 (使用Apache POI)",
                new GenerationStatistics(
                    stats.slidesGenerated(),
                    0, // POI不支持动画
                    processingTime,
                    getFileSize(outputPath)
                ),
                null
            );
            
        } catch (Exception e) {
            logger.error("POI演示文稿生成失败", e);
            return new GenerationResult(
                false,
                "生成失败: " + e.getMessage(),
                null,
                e
            );
        }
    }
    
    /**
     * 配置演示文稿属性
     */
    private void configurePresentationProperties(XMLSlideShow presentation, PresentationConfig config) {
        // 设置文档属性
        var properties = presentation.getProperties();
        properties.getCoreProperties().setTitle(config.metadata().title());
        properties.getCoreProperties().setCreator(config.metadata().author());
        
        // 设置幻灯片尺寸 (16:9)
        Dimension pageSize = new Dimension(1920, 1080);
        presentation.setPageSize(pageSize);
        
        logger.debug("配置POI演示文稿属性完成");
    }
    
    /**
     * 生成幻灯片
     */
    private GenerationStatistics generateSlides(XMLSlideShow presentation, PresentationConfig config) {
        int slidesGenerated = 0;
        
        for (PresentationConfig.SlideConfig slideConfig : config.slides()) {
            XSLFSlide slide = createSlide(presentation, slideConfig);
            slidesGenerated++;
            
            // 渲染内容
            if (slideConfig.content() != null) {
                renderSlideContent(slide, slideConfig.content());
            }
            
            // POI不支持复杂动画，记录警告
            if (slideConfig.animations() != null && !slideConfig.animations().isEmpty()) {
                logger.warn("幻灯片 {} 包含 {} 个动画效果，但POI引擎不支持动画", 
                           slideConfig.index(), slideConfig.animations().size());
            }
            
            logger.debug("完成幻灯片 {} 生成", slideConfig.index());
        }
        
        return new GenerationStatistics(slidesGenerated, 0, 0, 0);
    }
    
    /**
     * 创建单张幻灯片
     */
    private XSLFSlide createSlide(XMLSlideShow presentation, PresentationConfig.SlideConfig slideConfig) {
        // 创建幻灯片
        XSLFSlide slide = presentation.createSlide();
        
        // 设置背景
        if (slideConfig.layout() != null && slideConfig.layout().background() != null) {
            applyBackground(slide, slideConfig.layout().background());
        }
        
        // 添加标题
        if (slideConfig.title() != null && !slideConfig.title().trim().isEmpty()) {
            addTitle(slide, slideConfig.title());
        }
        
        return slide;
    }
    
    /**
     * 应用背景
     */
    private void applyBackground(XSLFSlide slide, java.util.Map<String, Object> background) {
        if (background.containsKey("color")) {
            String colorHex = (String) background.get("color");
            try {
                Color color = Color.decode(colorHex);
                slide.getBackground().setFillColor(color);
            } catch (Exception e) {
                logger.warn("背景颜色设置失败: {}", colorHex, e);
            }
        }
    }
    
    /**
     * 添加标题
     */
    private void addTitle(XSLFSlide slide, String title) {
        XSLFTextBox titleBox = slide.createTextBox();
        titleBox.setAnchor(new Rectangle2D.Double(100, 50, 800, 100));
        
        XSLFTextParagraph paragraph = titleBox.addNewTextParagraph();
        XSLFTextRun textRun = paragraph.addNewTextRun();
        textRun.setText(title);
        textRun.setFontSize(32.0);
        textRun.setBold(true);
        textRun.setFontColor(Color.BLACK);
    }
    
    /**
     * 渲染幻灯片内容
     */
    private void renderSlideContent(XSLFSlide slide, java.util.List<PresentationConfig.ContentElement> content) {
        for (PresentationConfig.ContentElement element : content) {
            switch (element.type().toLowerCase()) {
                case "text":
                    renderTextContent(slide, element);
                    break;
                case "image":
                    renderImageContent(slide, element);
                    break;
                case "shape":
                    renderShapeContent(slide, element);
                    break;
                case "video":
                    logger.warn("POI不支持视频内容: {}", element.data().get("path"));
                    break;
                default:
                    logger.warn("不支持的内容类型: {}", element.type());
                    break;
            }
        }
    }
    
    /**
     * 渲染文本内容
     */
    private void renderTextContent(XSLFSlide slide, PresentationConfig.ContentElement element) {
        String text = (String) element.data().get("text");
        if (text == null) return;
        
        XSLFTextBox textBox = slide.createTextBox();
        textBox.setAnchor(new Rectangle2D.Double(
            element.position().x(),
            element.position().y(),
            element.position().width(),
            element.position().height()
        ));
        
        XSLFTextParagraph paragraph = textBox.addNewTextParagraph();
        XSLFTextRun textRun = paragraph.addNewTextRun();
        textRun.setText(text);
        
        // 应用样式
        if (element.style() != null) {
            applyTextStyle(textRun, element.style());
        }
        
        logger.debug("渲染文本内容: {}", text.substring(0, Math.min(50, text.length())));
    }
    
    /**
     * 应用文本样式
     */
    private void applyTextStyle(XSLFTextRun textRun, java.util.Map<String, Object> style) {
        if (style.containsKey("font_size")) {
            Object fontSize = style.get("font_size");
            if (fontSize instanceof Number) {
                textRun.setFontSize(((Number) fontSize).doubleValue());
            }
        }
        
        if (style.containsKey("font_family")) {
            String fontFamily = (String) style.get("font_family");
            textRun.setFontFamily(fontFamily);
        }
        
        if (style.containsKey("color")) {
            String colorHex = (String) style.get("color");
            try {
                Color color = Color.decode(colorHex);
                textRun.setFontColor(color);
            } catch (Exception e) {
                logger.warn("文本颜色设置失败: {}", colorHex, e);
            }
        }
    }
    
    /**
     * 渲染图像内容
     */
    private void renderImageContent(XSLFSlide slide, PresentationConfig.ContentElement element) {
        String imagePath = (String) element.data().get("path");
        if (imagePath == null) return;
        
        try (FileInputStream imageStream = new FileInputStream(imagePath)) {
            PictureData pictureData = slide.getSlideShow().addPicture(imageStream, PictureData.PictureType.PNG);
            
            XSLFPictureShape picture = slide.createPicture(pictureData);
            picture.setAnchor(new Rectangle2D.Double(
                element.position().x(),
                element.position().y(),
                element.position().width(),
                element.position().height()
            ));
            
            logger.debug("渲染图像内容: {}", imagePath);
            
        } catch (Exception e) {
            logger.error("图像加载失败: {}", imagePath, e);
        }
    }
    
    /**
     * 渲染形状内容
     */
    private void renderShapeContent(XSLFSlide slide, PresentationConfig.ContentElement element) {
        String shapeType = (String) element.data().getOrDefault("shape_type", "rectangle");
        
        XSLFAutoShape shape = slide.createAutoShape();
        shape.setAnchor(new Rectangle2D.Double(
            element.position().x(),
            element.position().y(),
            element.position().width(),
            element.position().height()
        ));
        
        // 应用样式
        if (element.style() != null) {
            applyShapeStyle(shape, element.style());
        }
        
        logger.debug("渲染形状内容: {}", shapeType);
    }
    
    /**
     * 应用形状样式
     */
    private void applyShapeStyle(XSLFAutoShape shape, java.util.Map<String, Object> style) {
        if (style.containsKey("fill_color")) {
            String colorHex = (String) style.get("fill_color");
            try {
                Color color = Color.decode(colorHex);
                shape.setFillColor(color);
            } catch (Exception e) {
                logger.warn("形状填充颜色设置失败: {}", colorHex, e);
            }
        }
        
        if (style.containsKey("border_color")) {
            String colorHex = (String) style.get("border_color");
            try {
                Color color = Color.decode(colorHex);
                shape.setLineColor(color);
            } catch (Exception e) {
                logger.warn("形状边框颜色设置失败: {}", colorHex, e);
            }
        }
    }
    
    /**
     * 保存演示文稿
     */
    private void savePresentation(XMLSlideShow presentation, Path outputPath) throws Exception {
        try (FileOutputStream out = new FileOutputStream(outputPath.toFile())) {
            presentation.write(out);
        }
        
        logger.info("POI演示文稿保存完成: {}", outputPath);
    }
    
    private long getFileSize(Path filePath) {
        try {
            return java.nio.file.Files.size(filePath);
        } catch (Exception e) {
            return 0;
        }
    }
}